/*bfs从出口开始搜索
   1. 先访问一个格子四个邻格，若 ：
邻格离出口距离>当前格离出口距离+1，邻格离出口距离=当前格离出口距离+1,邻格加入搜索队列
    2. 如果该格有传送门,取出传送门目的格,若 ：
目的格离出口距离>当前格离出口距离+1，目的格离出口距离=当前格离出口距离+1,目的格加入搜索队列*/

import java.util.*;
public class Main {
    static int[][] dist; //每个格子离出口距离
    static int n,m;
    static int[] drx= {1,0,-1,0};
    static int[] dry= {0,1,0,-1};//方向
    static HashMap<Integer, ArrayList<Integer>> csms = new HashMap<>();//储存传送门的哈希表，
    //键是格子的索引 (x*n+y)，值是这个传送门的目的地,（一个传送门可有多个目的地）

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        n=scan.nextInt();
        m=scan.nextInt();
        dist = new int[n][n];
        for(int i=0;i<n;i++) {
            Arrays.fill(dist[i],Integer.MAX_VALUE);//初始距离为int上限
        }
        dist[n-1][n-1]=0;

        for(int i=0;i<m;i++) {
            int x1 = scan.nextInt()-1;
            int y1 = scan.nextInt()-1;
            int x2 = scan.nextInt()-1;
            int y2 = scan.nextInt()-1;
            int p1 = g(x1, y1);//传送门的两个端口
            int p2 = g(x2, y2);
            //将两个端口都加入哈希表
            if(csms.containsKey(p1)) {
                csms.get(p1).add(p2);
            }else {
                //首次加入
                ArrayList<Integer> al = new ArrayList<>();
                al.add(p2);
                csms.put(p1, al);
            }

            if(csms.containsKey(p2)) {
                csms.get(p2).add(p1);
            }else {
                ArrayList<Integer> al1 = new ArrayList<>();
                al1.add(p1);
                csms.put(p2, al1);
            }
        }
        scan.close();
        bfs();
        int sum=0;
        for(int i=0;i<n;i++) {
            for(int j=0;j<n;j++) {
                sum+=dist[i][j];
            }
        }
        System.out.printf("%.2f",sum*1.0/(n*n));

    }
    public static void bfs() {
        LinkedList<Integer> q = new LinkedList<>();//搜索队列
        q.offerLast(g(n-1, n-1));//加入出口

        while(!q.isEmpty()) {
            int pos = q.pollFirst();//当前格子
            int x = pos/n;
            int y = pos%n;//转化为x,y索引
            for(int k=0;k<4;k++) {
                //探索四个邻格
                int xx= x+drx[k];
                int yy = y+dry[k];
                if(xx<0 || yy<0 || xx>=n || yy>=n) continue;
                if(dist[xx][yy] > dist[x][y] +1) {
                    dist[xx][yy]=dist[x][y]+1;
                    q.offerLast(g(xx, yy));
                }
            }
            //若该格有传送门
            if(csms.containsKey(pos)) {
                //若当前格有传送门
                ArrayList<Integer> dests = csms.get(pos);//遍历该传送门的各个目的格
                for(int dest : dests) {
                    int dtx = dest/n;
                    int dty = dest%n;
                    if(dist[dtx][dty] > dist[x][y]+1) {
                        dist[dtx][dty] = dist[x][y]+1;
                        q.offerLast(g(dtx,dty));
                    }
                }
            }
        }
    }
    //求出一个格子的索引，用整数索引可以避免重写equals和hashcode
    public static int g(int x,int y) {
        return x*n+y;
    }
}